package com.qqt.csr.order.utils;

import com.qqt.csr.common.utils.CacheKeyUtil;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

/**
 * @author:
 * @date:
 */
@Component
public class OrderNoGenerator {
    @Autowired
    private RedissonClient redissonClient;

    /**
     * 客服工单前缀
     */
    public static final String WORK_ORDER_PREFIX = "WO";

    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyMMddHHmmssSSS");

    /**
     * 生成订单号
     *
     * @param orderPrefix
     * @param userId
     * @return 订单号前缀2位+年份后2位+月份后2位+日期后2位+时间戳后9位+用户id后9位+原子自增6位
     */
    public String generateOrderNo(String orderPrefix, Long userId) {
        return generateOrderNo(orderPrefix, userId.toString());
    }

    /**
     * 生成订单号
     *
     * @param orderPrefix
     * @param userId
     * @return 订单号前缀2位+年份后2位+月份后2位+日期后2位+时间戳后9位+用户id后9位+原子自增6位
     */
    public String generateOrderNo(String orderPrefix, String userId) {
        // 获取当前时间的格式化字符串，精确到毫秒
        String timeStr = getTimeStr();

        // 截取用户ID的后9位，确保不超过长度限制
        String userIdStr = subUserId(userId);

        // 原子自增6位，不足6位前面补0
        String incrementStr = getIncrement(userIdStr);

        // 订单号前缀2位+年份后2位+月份后2位+日期后2位+时间戳后9位+用户id后9位+原子自增6位
        return orderPrefix + timeStr + userIdStr + incrementStr;
    }

    /**
     * 年份后2位+月份后2位+日期后2位+时间戳后9位
     *
     * @return
     */
    private String getTimeStr() {
        String timeStr = LocalDateTime.now().format(FORMATTER);
        return timeStr.substring(0, 2) + timeStr.substring(2, 4) + timeStr.substring(4, 6) + timeStr.substring(6, 15);
    }

    /**
     * 截取用户ID的后9位，确保不超过长度限制
     *
     * @param userId
     * @return
     */
    private String subUserId(String userId) {
        if (userId.length() > 9) {
            return userId.substring(userId.length() - 9);
        } else {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 9 - userId.length(); i++) {
                sb.append("0");
            }
            return  sb.append(userId).toString();
        }
    }

    /**
     * 原子自增6位，不足6位前面补0
     *
     * @param userId
     * @return
     */
    private String getIncrement(String userId) {
        RLock lock = redissonClient.getLock(String.format(CacheKeyUtil.Order.ORDER_NO_INCREMENT_LOCK_KEY, userId));
        lock.lock(3L, TimeUnit.SECONDS);

        try {
            long increment = 0L;
            String incrementKey = String.format(CacheKeyUtil.Order.ORDER_NO_INCREMENT, userId);
            if (redissonClient.getAtomicLong(incrementKey).isExists()) {
                increment = redissonClient.getAtomicLong(incrementKey).getAndIncrement();
                if (increment > 999999L) {
                    redissonClient.getAtomicLong(incrementKey).delete();
                    increment = redissonClient.getAtomicLong(incrementKey).getAndIncrement();
                    redissonClient.getAtomicLong(incrementKey).expire(1, TimeUnit.DAYS);
                }
            } else {
                increment = redissonClient.getAtomicLong(incrementKey).getAndIncrement();
                redissonClient.getAtomicLong(incrementKey).expire(1, TimeUnit.DAYS);
            }
            return String.format("%06d", increment % 1000000L);
        } finally {
            lock.unlock();
        }
    }
}
